package com.highspeed.bdk.service.security.user;

import com.bianmaba.spring.data.jpa.service.BaseService;
import com.bianmaba.spring.security.util.PasswordEncoderFactory;
import com.highspeed.bdk.bean.base.LocalUserDetails;
import com.highspeed.bdk.bean.entity.security.Role;
import com.highspeed.bdk.bean.entity.security.User;
import com.highspeed.bdk.repository.security.user.UserRepository;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by chenjiabin on 2018/3/23.
 */
@Service
@Transactional
public class UserService extends BaseService<User, String> implements IUserService {
    private static final Logger LOG = LoggerFactory.getLogger(UserService.class);
    @Autowired
    private UserRepository repository;

    @Override
    public UserRepository getRepository() {
        return repository;
    }

    @Override
    public <S extends User> S save(S entity) {
        PasswordEncoder passwordEncoder = PasswordEncoderFactory.getPasswordEncode("MD5");
        if (StringUtils.isEmpty(entity.getId())) {
            String user = SecurityContextHolder.getContext().getAuthentication().getName();
            entity.setCreator(user);
            String encodedPwd = passwordEncoder.encode(entity.getPassword());
            entity.setPassword("{MD5}" + encodedPwd);
        } else {
            User old = findOne(entity.getId());
            if (old != null) {
                if (!old.getPassword().equals(entity.getPassword())) {
                    String encodedPwd = passwordEncoder.encode(entity.getPassword());
                    entity.setPassword("{MD5}" + encodedPwd);
                }
            }
        }
        S user = super.save(entity);
        return user;
    }

    @Override
    public <S extends User> List<S> save(Iterable<S> entities) {
        List<S> users = new ArrayList<>(0);
        for (S entity : entities) {
            S user = save(entity);
            users.add(user);
        }
        return users;
    }

    @Override
    public LocalUserDetails updateCurrentUserinfo(User entity) {

        User old = repository.getOne(entity.getId());
        if (old != null) {
            old.setName(entity.getName());
            old.setEmail(entity.getEmail());
            User user = save(old);

            List<Role> roles = user.getRoles();
            List<SimpleGrantedAuthority> authorities = new ArrayList<SimpleGrantedAuthority>(0);
            for (Role role : roles) {
                authorities.add(new SimpleGrantedAuthority(role.getName()));
            }
            return new LocalUserDetails(user.getId(), user.getName(), user.getEmail(), user.getUsername(), user.getPassword(), user.getEnabled(),
                    user.getAccountExpiringDate().getTime() > System.currentTimeMillis(),
                    user.getCredentialsExpiringDate().getTime() > System.currentTimeMillis(),
                    !user.getLocked(), authorities);
        }
        return null;
    }

    @Override
    public User findByUsername(String username) {
        User user = repository.findByUsername(username);
        return user;
    }

    @Override
    public LocalUserDetails getCurrentUser() {
        Object obj = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        if (obj instanceof LocalUserDetails) {
            LocalUserDetails user = (LocalUserDetails) obj;
            return user;
        }
        return null;
    }
}
